#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <future>

/**
 * C++ 类用于同步对共享资源的访问。
 *
 */

//创建一个全局 mutex 对象
std::mutex mtx;
//共享资源
int shared_resource = 0;

//线程函数
void increment(){
    std::lock_guard<std::mutex> lock(mtx);
    ++shared_resource;
    std::cout << "Incremented shared_resource to " << std::endl;
    //lock 在 lock_guard 离开作用域时自动释放
}

//lock_guard 自动管理锁的声明周期,离开函数自动释放锁
void print_thread_id(int id){
    std::lock_guard<std::mutex> lock(mtx);
    //执行操作
    std::cout << "Thread ID: " << id << std::endl;
    //自动释放锁
}

//unique_lock 提供了比std::lock_guard更灵活的锁管理
void print_thread_id_fuc(int id){
    std::unique_lock<std::mutex> lock(mtx);
    //执行操作
    std::cout << "Thread ID: " << id << std::endl;
    //手动解锁
    lock.unlock();
}

//condition_variable用于线程间的等待和通知
std::condition_variable cv;
bool ready = false;

void print_id(int id){
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock,[]{return ready;});
    std::cout << "Thread ID: " << id << std::endl;
}

void set_read(){
    std::unique_lock<std::mutex> lock(mtx);
    ready = true;
    cv.notify_all();
}

//std::future 和 std::promise 用于线程间的结果传递

void calculate_square(std::promise<int> && p,int x){
    p.set_value(x * x);
}

//std::async 启动异步任，并返回一个std::future
int calculate_square2(int x){
    return x * x;
}

int main() {

   /* std::thread t1(increment);
    std::thread t2(increment);

    if (t1.joinable()){
        t1.join();
    }

    if (t2.joinable()){
        t2.join();
    }

    std::cout << "Final value of shared_resource : " << shared_resource << std::endl;*/

    /*std::thread t1(print_id,1);
    std::thread t2(print_id,2);

    std::this_thread::sleep_for(std::chrono::seconds(1));
    set_read();

    t1.join();
    t2.join();*/


    /*std::promise<int> p;
    std::future<int> f = p.get_future();
    std::thread t(calculate_square,std::move(p),5);
    std::cout << "Square : " << f.get() << std::endl;
    t.join();*/
    std::future<int> result = std::async(calculate_square2,5);
    std::cout << "Square: " << result.get() << std::endl;

    return 0;
}
